package com.qf.test.shiro;

import com.qf.test.pojo.DtsAdmin;
import com.qf.test.service.AdminService;
import com.qf.test.service.PermissionService;
import com.qf.test.service.RoleService;
import com.qf.test.util.bcrypt.BCryptPasswordEncoder;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;

public class AdminAuthorizingRealm extends AuthorizingRealm {

    @Autowired
    private AdminService adminService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;
    /**
     * 用户登陆后 对用户进行授权 授予对应得角色和权限
     * @param principal
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        //1.获取认证的当前用户对象 这里将参数强制转换成我们自己封装的用户实体类对象
        DtsAdmin admin  = (DtsAdmin) getAvailablePrincipal(principal);
        //2.获取用户对下个获取角色ids
        Integer[] roleIds = admin.getRoleIds();
        //3.根据角色id集合到数据库中查找对应的角色名称集合
        Set<String> roleSet = roleService.queryByIds(roleIds);
        //4.根据角色的Id 到数据库中查询到对用的字符串集合
        Set<String> permSet = permissionService.queryPermissonByRoleIds(roleIds);
        //5.角色名称集合 和权限字符集合交给shiro管理
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //6.返回封装后的shiro对象
        info.setRoles(roleSet);
        info.setStringPermissions(permSet);
        return info;
    }

    /**
     * 接受页面传入得用户名密码 根据数据库得用户名密码校验
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //1.获取用户页面 输入的用户名 密码
        UsernamePasswordToken UserNamePwd=(UsernamePasswordToken) token;
        String username = UserNamePwd.getUsername();
        String password=  new String(UserNamePwd.getPassword());


        //2.判断用户名是否为空 返回异常 提示信息
        if(StringUtils.isEmpty(username)){
            throw new AccountException("用户名为空！");

        }
        //3.判断用户密码是否为空 返回异常提示信息
        if(StringUtils.isEmpty(password)){
            throw new AccountException("密码为空！");

        }
        //4.根据用户名  获取用户对象的集合
        List<DtsAdmin> userlist = adminService.findAdminByUserName(username);
        //5.判断如果获取不到对象 返回异常提示信息
        if(userlist==null||userlist.size()==0){
            throw new AccountException("用户名错误！");
        }
        //6.如果用户对象大于1个 那么说明存在同名账户 不允许登录
        if(userlist.size()>=2){
            throw new UnknownAccountException("存在同名账户，请联系管理员");
        }
        DtsAdmin admin = userlist.get(0);
        //7.判断如果用户名密码不正确返回异常提示信息
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        //BCrypt工具进行校验 密码使用的BCrypt算法进行的加密
        //第一个参数是明文密码  第二个参数是加密后的密码，返回校验的结果
        if(!encoder.matches(password,admin.getPassword())){
            throw new UnknownAccountException("密码错误");
        }
        //8.封装shiro指定的对象交给shiro处理
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(admin, password, this.getName());
        return info;
    }
}
